#!/usr/bin/python
# -*- coding: utf-8 -*-
#websocket server
#frome http://stackoverflow.com/questions/18240358/html5-websocket-connecting-to-python
#http://www.oschina.net/code/snippet_176897_5938
#http://yz.mit.edu/wp/web-sockets-tutorial-with-simple-python-server/

import socket, hashlib, base64
import SocketServer
import threading

MAGIC = '258EAFA5-E914-47DA-95CA-C5AB0DC85B11'
HSHAKE_RESP = "HTTP/1.1 101 Switching Protocols\r\n" + \
            "Upgrade: websocket\r\n" + \
            "Connection: Upgrade\r\n" + \
            "Sec-WebSocket-Accept: %s\r\n" + \
            "\r\n"
HOST = ''
PORT = 9876
class ThreadedTcpRequestHandler(SocketServer.BaseRequestHandler):
	def handle(self):
		try:
			start = True
			while True:
				if start:
					print "first"
					self.process_websocket_head()
					start = False
				else:
					if 2 == self.process_websocket_data():
						print "null 2  \n\n"
						break
				#data = self.request.recv(1024)
				#cur_thread = threading.current_thread()
				#response = "{}:{}".format(cur_thread.name, data)
				#print data
				#print "response:",response
				#self.request.sendall(response)

		except Exception,Ex:
			print Exception, ":", Ex

	def process_websocket_head(self):
		data = self.request.recv(1024)
		headers = {}
		lines = data.splitlines()
		for l in lines:
			parts = l.split(": ", 1)
			if len(parts) == 2:
				headers[parts[0]] = parts[1]
		headers['code'] = lines[len(lines) - 1]
		key = headers['Sec-WebSocket-Key']
		resp_data = HSHAKE_RESP % ((base64.b64encode(hashlib.sha1(key+MAGIC).digest()),))
		self.request.sendall(resp_data)

	#recv data ,process and send
	def process_websocket_data(self):
		data = self.request.recv(1024)
		if not data: 
			return 1
		databyte = bytearray(data)
		datalen = (0x7F & databyte[1])
		str_data = ''
		if(datalen > 0):
			mask_key = databyte[2:6]
			masked_data = databyte[6:(6+datalen)]
			unmasked_data = [masked_data[i] ^ mask_key[i%4] for i in range(len(masked_data))]
			str_data = str(bytearray(unmasked_data))
		print "we recv data:->%s<- "%str_data
		#ret_data = py_data_process.process(str_data)
		ret_data = str_data
		if not ret_data or ret_data == '':
			return 2
		ret_data = self.encode_data(ret_data)

		print "\n\nwill send data:->%s<-"%ret_data ,"type:", type(ret_data), len(ret_data)
		'''
		resp = bytearray([0b10000001, len(ret_data)])
		for d in bytearray(ret_data):
			resp.append(d)
		'''
		print "send data:",ret_data
		self.request.sendall(ret_data)
		return 0
	
	def encode_data(self, data):
		resp = bytearray([0b10000001])
		data_len = len(data)
		if data_len <= 125:
			resp.append(chr(data_len))
		elif data_len <= 65535:
			resp.append(chr(126))
			resp.append(chr((data_len>>8) & 255))
			resp.append(chr((data_len) & 255))
			index = 4
		elif data_len >= 65536:
			resp.append(chr(127))
			resp.append(chr((data_len>>56) & 255))
			resp.append(chr((data_len>>48) & 255))
			resp.append(chr((data_len>>40) & 255))
			resp.append(chr((data_len>>32) & 255))
			resp.append(chr((data_len>>24) & 255))
			resp.append(chr((data_len>>16) & 255))
			resp.append(chr((data_len>>8)  & 255))
			resp.append(chr((data_len)     & 255))
		resp += data
		return resp
		pass

class ThreadedTCPServer(SocketServer.ThreadingMixIn,\
		SocketServer.TCPServer):
	def server_bind(self):
		print("this is in server_bind")
		self.socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
		self.socket.bind(self.server_address)
		self.server_address = self.socket.getsockname()
	pass

if __name__ == '__main__':
	#HOST, PORT = 'localhost', 9999

	server = ThreadedTCPServer((HOST, PORT), ThreadedTcpRequestHandler)

	server_thread = threading.Thread(target=server.serve_forever)
	server_thread.deamon = True
	server_thread.start()
	print "server loop running in thread:", server_thread.name

	#server.shutdown()
